home *** CD-ROM | disk | FTP | other *** search
- /*t RX50INIT -- Initialize RX50 MS-DOS Data Diskette */
- /*----------------------------------------------------------------------*/
- /* */
- /* RX50INIT -- Initialize RX50 MS-DOS Data Diskette */
- /* */
- /*----------------------------------------------------------------------*/
-
- #define PROGREV "[1.03]" /* 09-Dec-84 14:00 */
-
- /* Copyright (c) 1984 by Robert F. Morse
- ** 17 Bowdoin Street
- ** Cambridge, MA 02138
- **
- **
- ** Function: Initialize the directory and FAT of an RX50 diskette to
- ** be used as an MS-DOS data diskette for a DECmate or Rainbow.
- **
- ** Invocation:
- **
- ** RX50INIT [d:] [volume-name]
- **
- ** The drive letter is optional; D is the default. The volume name
- ** is optional; if none is given, none is written in the directory.
- **
- ** Notes: This version is for an IBM PC-AT and requires that device
- ** driver RX50DRVR.SYS be loaded when the system was booted. This
- ** driver maps references to drive D: to the AT's high-capacity drive
- ** (normally drive A:) and sets that drive to handle the 80-track
- ** 10-sector RX50 format.
- */
-
- #include "standard.h"
- #include "msdosdir.h"
- #include "msdosdpb.h"
-
- #define SECTOR_SIZE 512
-
- #define FAT_SECTORS 3
- #define FAT_BUFSIZE (FAT_SECTORS * SECTOR_SIZE)
- #define FAT_START_1 20
- #define FAT_START_2 23
-
- #define CLUSTER_EOF 0x0FFF
- #define CLUSTER_MEDIA 0x0FFA
-
- #define DIR_SECTORS 6
- #define DIR_BUFSIZE (DIR_SECTORS * SECTOR_SIZE)
- #define DIR_START 26
-
- #define DPB_MEDIA 0xFA
- #define DPB_MAX_CLUSTER 769
-
- char *malloc();
- /*^---------- Global Constants & Data -------------*/
-
- char *fatbuf;
- MSDOS_Dir *dirbuf;
-
- char vol_name[12] = " ";
-
- uint target_unit = 3; /* default drive is D: */
-
- char *disk_errs[] ={ "Write protect", /* 0 */
- "Invalid unit", /* 1 */
- "Not ready", /* 2 */
- "Bad command", /* 3 */
- "Data CRC", /* 4 */
- "Bad request", /* 5 */
- "Seek", /* 6 */
- "Unknown media", /* 7 */
- "Sector not found", /* 8 */
- "Out of paper", /* 9 */
- "Write fault", /* 10 */
- "Read fault", /* 11 */
- "I/O", /* 12 */
- "", /* 13 */
- "", /* 14 */
- "Invalid disk change"}; /* 15 */
-
- /* BOOT BLOCK, to be written in block 0 */
-
- struct {byte jump[3];
- char oem_name[8];
-
- int bytes_sector;
- byte sects_alu;
- int reserved_sects;
- byte num_fats;
- int num_dirents;
- int total_sectors;
- byte fat_id;
- int fat_sectors;
-
- int sects_track;
- int num_heads;
- int hidden_sects; } boot_block = {
-
- {0xE9, 0x00, 0x00},
- {'D', 'E', 'C', '-', 'R', 'X', '5', '0'},
- 512, 1, 20, 2, 96, 800, 0xFA, 3,
- 10, 1, 0 };
-
- /*^*/
-
- #define DOS_GETDATE 0x2A
- #define DOS_GETTIME 0x2C
-
- typedef struct {
- unsigned Wyr;
- unsigned Wmo;
- unsigned Wda;
- unsigned Whr;
- unsigned Wmn;
- unsigned Wsc;
- unsigned Whn;
- unsigned Wdw;
- } When;
-
- When now;
-
- timestamp (w) When *w;
- {
- RuptRegs reg;
-
- getsegs (®);
-
- doscall (DOS_GETDATE, ®);
- w->Wyr = reg.w.cx;
- w->Wmo = reg.b.dh;
- w->Wda = reg.b.dl;
- w->Wdw = reg.b.al;
-
- doscall (DOS_GETTIME, ®);
- w->Whr = reg.b.ch;
- w->Wmn = reg.b.cl;
- w->Wsc = reg.b.dh;
- w->Whn = reg.b.dl;
- }
- /*^------------------------------------------------------------*/
- write_sect (unit, block, count, buffer) char *buffer;
- /*---------------------------------------------------------------
- ** Write <count> sectors beginning with sector <block> on <unit>
- ** from <*buffer>, returning 0 if OK or aborting the program if
- ** there is an uncorrectable error.
- */
-
- #define MSDOS_WRITE 0x26
- #define CF_MASK 0x0001
-
- { RuptRegs reg;
- char ch;
- again:
- getsegs (®);
- reg.w.ax = unit;
- reg.w.bx = (uint) buffer;
- reg.w.cx = count;
- reg.w.dx = block;
-
- if (intcall (MSDOS_WRITE, ®) & CF_MASK)
- {
- cputf ("\n\n%s error writing drive %c:\nAbort, Retry? ",
- disk_errs[reg.b.al], unit + 'A');
- do ch = cgetcne();
- while (strchr ("AaRr\003", ch) == NULL);
- cputc ('\n');
- if (toupper (ch) == 'R')
- goto again;
- cputs ("CANCELLED");
- _exit (1);
- }
- else
- return (0);
- }
-
-
-
- get_fat (fat, n) char *fat;
- { int w;
- w = * (int*) &fat[(n*3)/2];
- if (n & 1)
- w >>= 4;
- return(w & 0x0FFF);
- }
-
- put_fat (fat, n, val) char *fat;
- { int *w;
- w = (int*) &fat[(n*3)/2];
- if (n & 1)
- *w = (*w & 0x000F) | ((val << 4) & 0xFFF0);
- else
- *w = (*w & 0xF000) | (val & 0xFFF);
- }
- /*^-----------------------------------*/
- main (argc, argv) char *argv[];
- /*------------------------------------*/
- { int n, x, y, err;
- char ch;
- MSDOS_Dir *p;
- MSDOS_Dpb dpb;
- RuptRegs reg;
- unsigned int attr;
- unsigned int clus;
-
- cputf ("%-45.45s%10.10s%24.24s\n%79.79s",
- "Initialize DEC RX50 Data Diskette",
- PROGREV,
- "Copyright (c) 1984",
- "by Robert F. Morse");
-
- n = 1;
- /*
- ** Get the drive letter (if any) from the command arguments.
- */
- if (n < argc)
- {
- if (argv[n][1] == ':')
- {
- if ( ((target_unit = toupper (argv[n][0]) - 'A') < 25) &&
- (strlen (argv[n]) == 2) )
- ++n;
- else
- {
- cputf ("\n INVALID SOURCE DRIVE LETTER %s", argv[n]);
- _exit (1);
- }
- }
- }
- /*
- ** Get the volume name (if any) from the command arguments.
- */
- if (n < argc)
- {
- for (x = 0; x < 11; ++x)
- {
- if ((ch = argv[n][x]) == '\0')
- break;
- if (isalnum (ch) || (ch == '-'))
- vol_name[x] = toupper (ch);
- else
- {
- cputf ("\n INVALID CHARACTER '%c' IN VOLUME NAME %s", ch, argv[n]);
- _exit (1);
- }
- }
- }
- /*
- ** Allocate memory for disk data buffers.
- */
- if ( ((fatbuf = malloc(FAT_BUFSIZE)) == NULL) ||
- ((dirbuf = (MSDOS_Dir*) malloc(DIR_BUFSIZE)) == NULL) )
- {
- cputs( "\n INSUFFICIENT MEMORY");
- _exit(1);
- }
- /*
- ** Ask the operator to insert a diskette in the target drive.
- */
- cputf(
- "\n Insert diskette into drive \033[7m %c \033[m and press ENTER ",
- target_unit + 'A');
- do {
- ch = cgetcne ();
- if (ch == 3) /* quit on ctrl/C */
- {
- cputf ("\nCANCELLED");
- _exit (1);
- }
- } while (ch != '\r');
- /*
- ** Get the diskette's DPB to check that it is a possible RX50 and is NOT
- ** (horrors!) the hard disk. Also catches uninstalled drive letters.
- */
- reg.b.dl = target_unit + 1;
- doscall (0x32, ®);
- if (reg.b.al)
- {
- cputf ("\n DRIVE %c: NOT INSTALLED", target_unit + 'A');
- _exit (1);
- }
-
- peek (reg.w.ds, reg.w.bx, &dpb, sizeof(dpb));
- if ((dpb.Dpb_max_cluster != DPB_MAX_CLUSTER) ||
- (dpb.Dpb_media != DPB_MEDIA) )
- {
- cputf ("\n DRIVE %c: CANNOT HANDLE RX50 DISKETTES", target_unit + 'A');
- _exit (1);
- }
- /*
- ** Set up and write the FAT.
- **
- ** Note: This first attempt to write is on cylinder 2, which will fail
- ** with a sector-not-found if a 48-tpi diskette is in the drive.
- */
- setmem (fatbuf, FAT_BUFSIZE, 0x00);
-
- put_fat (fatbuf, 0, CLUSTER_MEDIA);
- put_fat (fatbuf, 1, CLUSTER_EOF);
-
- write_sect (target_unit, FAT_START_1, FAT_SECTORS, fatbuf);
- write_sect (target_unit, FAT_START_2, FAT_SECTORS, fatbuf);
- /*
- ** Set up and write the directory.
- */
- setmem (dirbuf, DIR_BUFSIZE, 0x00);
-
- timestamp (&now);
-
- if (vol_name[0] != ' ')
- {
- p = dirbuf;
- memcpy (p->Dir_name, vol_name, 11);
- p->Dir_attr = Dirattr_VOL;
- p->Dir_date.Dt_yr = now.Wyr - 1980;
- p->Dir_date.Dt_mo = now.Wmo;
- p->Dir_date.Dt_da = now.Wda;
- p->Dir_time.Dt_hr = now.Whr;
- p->Dir_time.Dt_mn = now.Wmn;
- p->Dir_time.Dt_sc = now.Wsc / 2;
- }
-
- write_sect (target_unit, DIR_START, DIR_SECTORS, dirbuf);
- /*
- ** Write the boot block in block 0.
- */
- setmem (fatbuf, SECTOR_SIZE, 0x00);
- memcpy (fatbuf, &boot_block, sizeof (boot_block));
- write_sect (target_unit, 0, 1, fatbuf);
- /*
- ** Write an all-zero sector in block 1 (the IBM FAT position).
- */
- setmem (fatbuf, SECTOR_SIZE, 0x00);
- write_sect (target_unit, 1, 1, fatbuf);
- /*
- ** Write an all-zero sector in block 10 to forstall any attempted DECmate boot
- */
- write_sect (target_unit, 10, 1, fatbuf);
- /*
- ** Done--announce success and exit.
- */
- cputs ("\n Diskette initialized");
- if (vol_name[0] != ' ')
- cputf (", volume name is %s", vol_name);
- _exit (0);
- }
- /******/
-